#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <list>
#include <memory>
#include <complex>
#include <algorithm>
#include <cassert>
#include <cstddef>
#include "include/FileClass.h"
#include "include/Urand.h"
#include "include/StringConv.h"
#include "src/TempTemp2.cc"
#include "include/Mytemplate.h"
#include "include/threadpool.h"
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
using namespace std;
// string 文件输出输入流 使用的类都是由类型定义的模版的特化！！！！！！！！！！
namespace hello
{
  template <class T, template <class U, class = allocator<U>> class Seq>
  class Container
  {
    Seq<T> seq;

  public:
    void push_back(const T &t)
    {
      seq.push_back(t);
    }
    // 没有typename 编译器会把iterator看作是Seq<T> 的一个静态数据成员，这是语法错误，因为要求他是一个类型
    typename Seq<T>::iterator begin()
    {
      return seq.begin();
    }
    typename Seq<T>::iterator end()
    {
      return seq.end();
    }
  };
}
class Firendly
{
  int i;

public:
  Firendly(int theInt)
  {
    i = theInt;
  }
  friend void f(const Firendly &);
  void g() { f(*this); }
};
void h()
{
  f(Firendly(1));
}
void f(const Firendly &fo)
{
  cout << fo.i << endl;
}
template <int n>
struct Factorial
{
  enum
  {
    val = Factorial<n - 1>::val * n
  };
};
template <>
struct Factorial<0>
{
  enum
  {
    val = 1
  };
};

// template <int n>
// struct Fib
// {
//   enum
//   {
//     val = Fib<n - 1>::val + Fib<n - 2>::val
//   };
// };
// template <>
// struct Fib<1>
// {
//   enum
//   {
//     val = 1
//   };
// };
// template <>
// struct Fib<0>
// {
//   enum
//   {
//     val = 0
//   };
// };

template <int n>
inline int power(int m)
{
  return power<n - 1>(m) * m;
};

template <>
inline int power<1>(int m)
{
  return m;
};

template <>
inline int power<0>(int m)
{
  return 1;
};
template <int n1, int n2>
struct Max
{
  enum
  {
    val = n1 > n2 ? n1 : n2
  };
};
bool gt15(int x){ return 15 < x;}
int main(int argc, char *argv[])
{
  cout << "hello world" << endl;

  // 3 深入了解字符串
  // c 语言中 字符串是字符数组，并且总是以二进制0为结尾

  // 3.2 创建并初始化c++字符串
  // string imBlank;
  // string hey("hello world1");
  // string hello = "hello world2";
  // string hello1 = hello;
  // cout << imBlank << endl;
  // cout << hey << endl;
  // cout << hello << endl;
  // cout << hello1 << endl;

  // cout << hello.size() << endl;
  //  介绍字符串的使用为主

  // 第四章 输入输出流
  // c 语言的 形式
  // try
  // {
  //     FileClass f("main2.cc");
  //     const int size = 100;
  //     char buf[size];
  //     while (fgets(buf, size, f.fp()))
  //     {
  //         fputs(buf, stdout);
  //     }
  // }
  // catch (FileClass::FileClassError &e)
  // {
  //     std::cerr << e.what() << '\n';
  // }

  // 4.2救助输入输出流
  //
  //  输入 输出流：  istream fstream
  //  文件输入 输出流： ifstream ofstream fstream

  // 可以为自己的类定义插入符和提取符，重载相关的运算符
  // 1.第一个参数定义成流（输入为istream，输出ostream）的非const引用
  // 2.执行向/从流中插入/提取数据的操作
  // 3.返回流的引用
  // 例子：Rectangle.CC

  // 4.2.2通常用法
  // 4.3 处理流错误  流状态4种
  // 4.4 文件输入输出流

  const int SZ = 100;
  char buf[SZ];
  // 5、深入理解模版
  // 模版两类：1.函数模版，2.类模版
  // 5.1 模版参数
  // （1）类型（系统固有类型或者用户自定义类型）
  // （2）编译时常数值
  // （3）其他模版

  // 第一种最简单的
  //     template <class T>
  // class Stack{
  //     T* data;
  //     size_t count;
  //  public:
  //     void push(const T& t);
  // }
  // 5.1.1 无类型模版参数
  // 一个无类型模版参数可以作为其中基础类型数组的大小
  //    template <class T,size_t N>
  //    class Stack{
  //        T data[N];
  //        size_t count;
  //     public:
  //        void push(const T& t);
  //    }
  // 当需要这个模版的一个实例时，必须为参数N提供一个编译时常数值
  // bitset类模版，是标准c++库中唯一一个使用了无类型模版参数
  // Urand<10> u;
  // cout << "rand" << endl;
  // for (int i = 0; i < 20; i++)
  // {
  //     cout << u() << endl;
  // }
  //    //具有默认值
  //    template <class T = int,size_t N = 100>
  //    class Stack{
  //        T data[N];
  //        size_t count;
  //     public:
  //        void push(const T& t);
  //    }

  // template <class _Tp, class _Allocator /* = allocator<_Tp> */>
  // class _LIBCPP_TEMPLATE_VIS vector {

  // 尽管不能再函数模版中使用默认的模版参数，却能够用模版参数作为普通函数的默认参数
  // template <class T>
  // T sum(T * b, T * e, T init = T())
  // {
  //     while (b != e)
  //         init += *b++;
  //     return init;
  // }

  // 5.1.3 模版类型的模版参数
  // 模版可以接受的第三种模版参数类型是另一个类的模版
  //   Container<int,10,Array> container;
  //   container.append(1);
  //   container.append(2);
  //   int*p=container.begin();
  //   while(p!=container.end()){
  //     cout<<*p++<<endl;
  //   }

  // 必须重复命名默认参数
  // array里面声明默认参数，则container也要声明默认参数
  // hello::Container<int, vector> vContainer;
  // vContainer.push_back(1);
  // vContainer.push_back(2);
  // for (vector<int>::iterator p = vContainer.begin(); p != vContainer.end(); p++)
  // {
  //   cout << *p << endl;
  // }

  // 5.1.4 typename关键字
  // 22行
  // 5.1.5 以template关键字作为提示？
  // 5.1.6 成员模版
  // 在另一个类或者类模版中声明的一个模版
  // complex类模版
  //  template<typename T> class complex{
  //   public:
  //     template<class X> complex(const complex<X>&)
  // }
  // 5.2.1 函数模版参数的类型推断
  // int z = min(i,j);
  // int z = min(i,j); i 如果为double类型，则错误
  // int z = min<double>(i,j); 这样解决

  // 若一个函数模版的返回类型是一个独立的模版参数，当调用它的时候就一定要明确指定它的类型，
  // 因为这时已经无法从函数参数中推断出它的类型了
  //  int i = 1234;
  //  cout << "i==" << toString(i) <<endl;
  //  float x = 567.89;
  //  cout << "x==" << toString(x) <<endl;
  //  complex<float> c(1.0,2.0);
  //  cout << "x==" << toString(c) <<endl;

  //  i =fromString<int>(string("1234"));

  // 如果有一个函数模版，它的模版参数既作为参数类型又作为返回类型，那么一定要首先声明函数的返回类型参数，
  // 否则不能省略掉函数参数表中的任何参数

  // 例子：
  //   template<typename R,typename P>
  // R  imp_cast(const P& p){
  //    return p;
  // }

  // 5.2.2 函数模版重载
  // 函数模版支持重载
  //  template<typename T> const T& min(const T& a ,const T& b){
  //    return (a<b)a?:b;
  //  }
  //  double min(double a ,double b){
  //    return (a<b)a?:b;
  //  }

  // 5.2.3以一个已生成的函数模版地址作为参数？
  // 5.2.4将函数应用到stl序列容器中
  // 5.2.5 函数模版的半有序
  // 如果在一组重载的函数模版中没有“特化程度最高”的模版，则会出现二义性，编译器将会报错

  // 5.3 模版的特化
  // 5.3.1 显示特化
  /*
  template<calss T> const T& min(const T& a,const T& b){
  return (a<b)? a:b;
  }
  template<>
  const char* const& min<const char*>(const char* const& a, const char* const& b){
   return (strcmp(a,b)<0)?a:b;
  }
   */

  // 5.3.2 半特化
  // 意味着在模版特化的某些方法中至少还有一个方法，其模版参数是开放的

  /*
  template<class T,class U>
  template<int,class U>
  template<class T,double>
  */

  // 5.3.3 一个例子 不看
  // 5.3.4 防止代码膨胀 ，不对不需要特化的代码特化

  // 5.4 名称查找问题

  // 5.4.1 关联参数查找
  // 5.4.2 模版与友元
  //   h();
  //   Firendly(2).g();

  // 5.5 模版编程中的习语
  // 5.6 模版元编程

  // 通过模版实现了递归
  cout << Factorial<12>::val << endl;

  // 5.6.1 编译时编程
  // 模版元编程就是完全的图灵机，因为它支持选择和循环
  // cout << Fib<5>::val << endl;
  // cout << Fib<20>::val << endl;

  // 1.编译时循环
  // 2.循环分解
  int m = 4;
  cout << power<3>(m) << endl;
  // 3.编译时选择
  cout << Max<10, 20>::val << endl;
  // 4.编译时断言

  //5.6.2表达式模版，//高性能，学！
  //高性能数学库的基础
  //例子：MyVector.cc
  //MyVector2.cc

  //5.7 模版编译模型 ，解决模版声明和实现在一个文件的问题！
  //5.7.1 包含模型
  //5.7.2 显式实例化
  //5.7.3 分离模型
   
  // MyTemplate<int> a(42);  // 使用已显式实例化的类型
  // a.print();              // 输出：Value: 42

  // MyTemplate<double> b(3.14);
  // b.print();              // 输出：Value: 3.14

  // processData(1.5f); 
  
  cout<<"chapter 6 begin:"<<endl;
  //6 通用算法
  //6.1 概述
  //copy算法
  //int 
  // int a[] = {10,20,30};
  // const size_t SIZE =sizeof a/sizeof(a[0]);
  // int b[SIZE];
  // copy(a,a+SIZE,b);
  // for(size_t i=0;i<SIZE;i++){
  //   assert(a[i]==b[i]);
  //   cout << b[i]<<endl;
  // }


  ///string
  // string a[] = {"hello","world","test"};
  // const size_t SIZE =sizeof a/sizeof(a[0]);
  // string b[SIZE];
  // copy(a,a+SIZE,b);
  // for(size_t i=0;i<SIZE;i++){
  //   assert(equal(a,a+SIZE,b));
  //   cout << b[i]<<endl;
  // }
  
  //vector
  // int a[] = {10,20,30};
  // const size_t SIZE =sizeof a/sizeof(a[0]);
  // vector<int> v1(a,a+SIZE);
  // vector<int> v2(SIZE);
  // copy(v1.begin(),v1.end(),v2.begin());
  // assert(equal(v1.begin(),v1.end(),v2.begin()));

  //6.1.1 判定函数
  // int a[] = {10,20,30};
  // const size_t SIZE =sizeof a/sizeof(a[0]);
  // int b[SIZE];
  // int* endb=remove_copy_if(a,a+SIZE,b,gt15);
  // int* beginb =b;
  // while (beginb!=endb)
  // {
  //   cout<<*beginb++<<endl;
  // }
  //8 运行时类型识别
  //当仅有一个指针或者引用指向基类型时，利用rtti可以找到一个对象的动态类型
  //简单来说就是向下类型转换，找到合适的类型
  //checkedCast.cc
  //9 多重继承
  //9.2接口继承
  //c++中所有的实现都是实现继承，不是能实现接口继承
  //c++中模拟接口继承常见的技术就是从一个仅包含声明的接口类中派生出一个类
  //例子：Interfaces.cc
  //Interfaces2.cc 模版实现更符合现代编程

  //9.3 实现继承
  //多重继承的一个共同用途包括使用混入类mixin，这些混入类的存在是为了通过继承来增加其他类的功能

  //9.4 重复子对象
  //当从某个基类继承时，可以在其派生类中得到那个基类的所有数据成员副本
  //9.5 虚基类
  //真正棱形继承方式

  //9.6 名字查找问题
  //消除二义性调用的方法，是以基类名来限定函数的调用
  //例子：BreakTie.cc
  //9.7 避免使用多重继承
  //9.8 扩充一个接口

  //10 设计模式
  ThreaPool& threadpool = ThreaPool::instance();
  threadpool.start(4);
  std::this_thread::sleep_for(std::chrono::seconds(5));
  return 0;
}
